#include <stdio.h>
#include <stdlib.h>
#include <sql.h>
#include <sqlext.h>
#include <string.h>
#include <sys/time.h>
#include <pthread.h>
#include <sqltypes.h>
#define MESSAGE_BUFFER_LEN 512
void print_error();
void end_unit_test();
int execute_cmd(SQLCHAR *sql);
int commit_exec();
/* ------------------------- 测试用常量宏定义 ------------------------------- */

#define STRING_DSN "og"

SQLHANDLE h_env = NULL;
SQLHANDLE h_conn = NULL;

/**
 * 
 *  默认savepoint是开启的。
 *  ForExtensionConnector=1 关闭savepoint，配置在odbc.ini里面
 * 
 * 
 * 
*/

/* 期盼函数返回SQL_SUCCESS */
#define RETURN_IF_NOT_SUCCESS(func)                                                                           \
        {                                                                                                     \
                SQLRETURN ret_value = (func);                                                                 \
                if (SQL_SUCCESS != ret_value)                                                                 \
                {                                                                                             \
                        print_error();                                                                        \
                        printf("\n failed line = %u: expect SQL_SUCCESS, but ret = %d", __LINE__, ret_value); \
                        return SQL_ERROR;                                                                     \
                }                                                                                             \
        }

SQLCHAR *sql_drop = "drop table if exists test_bindnumber_001";
SQLCHAR *sql_create = "create table test_bindnumber_001(f4 number, f5 number(10, 2),age timestamp without time zone)";
SQLCHAR *sql_insert = "insert into t2 values(1,'a');";
SQLCHAR *sql_select = "select 1 ";

void testconnnection()
{
        SQLHANDLE h_stmt = NULL;
        /* 查询 */
        RETURN_IF_NOT_SUCCESS(SQLAllocHandle(SQL_HANDLE_STMT, h_conn, &h_stmt));
        // RETURN_IF_NOT_SUCCESS(SQLPrepare(h_stmt, sql_select, SQL_NTS));
        // SQLExecute(h_stmt);
        SQLExecDirect(h_stmt, sql_select, SQL_NTS);
        // SQLFreeHandle(SQL_HANDLE_STMT, h_stmt);

        SQLEndTran(SQL_HANDLE_DBC, h_conn, SQL_COMMIT);
}

void sleep_time()
{
        printf("will sleep 20s ... \n");
        sleep(20);
}

int main()
{
        ;
        SQLRETURN ret_value;
        int i = 0;
        SQLHANDLE h_stmt = NULL;
        /* 申请环境句柄 */
        RETURN_IF_NOT_SUCCESS(SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &h_env));
        /* 进行连接前必须要先设置版本号 */
        RETURN_IF_NOT_SUCCESS(SQLSetEnvAttr(h_env, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0))
        /* 申请连接句柄 */
        RETURN_IF_NOT_SUCCESS(SQLAllocHandle(SQL_HANDLE_DBC, h_env, &h_conn));
        /* 关闭手动提交 */
        RETURN_IF_NOT_SUCCESS(SQLSetConnectAttr(h_conn, SQL_ATTR_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF, 0));
        /* 建立连接 */
        RETURN_IF_NOT_SUCCESS(SQLConnect(h_conn, STRING_DSN, SQL_NTS, NULL, SQL_NTS, NULL, SQL_NTS));

        // testconnnection();

        SQLCHAR Sqlstate[SQL_SQLSTATE_SIZE + 1];
        SQLINTEGER NativeError;
        SQLCHAR MessageText[MESSAGE_BUFFER_LEN];
        SQLSMALLINT TextLength;
        SQLRETURN ret = SQL_ERROR;

        // /* 插入 */
        SQLAllocHandle(SQL_HANDLE_STMT, h_conn, &h_stmt);
        SQLPrepare(h_stmt, sql_insert, SQL_NTS);
        SQLExecute(h_stmt);
        ret = SQLGetDiagRec(SQL_HANDLE_STMT, h_stmt, 1, Sqlstate, &NativeError, MessageText, MESSAGE_BUFFER_LEN, &TextLength);
        if (SQL_SUCCESS == ret)
        {
                printf("\n STMT ERROR-%05d %s", NativeError, MessageText);
                // return;
        }
        SQLFreeHandle(SQL_HANDLE_STMT, h_stmt);

        SQLAllocHandle(SQL_HANDLE_STMT, h_conn, &h_stmt);
        SQLPrepare(h_stmt, sql_insert, SQL_NTS);
        SQLExecute(h_stmt);
        ret = SQLGetDiagRec(SQL_HANDLE_STMT, h_stmt, 1, Sqlstate, &NativeError, MessageText, MESSAGE_BUFFER_LEN, &TextLength);
        if (SQL_SUCCESS == ret)
        {
                printf("\n STMT ERROR-%05d %s", NativeError, MessageText);
                // return;
        }
        SQLFreeHandle(SQL_HANDLE_STMT, h_stmt);

        ret_value = SQLEndTran(SQL_HANDLE_DBC, h_conn, SQL_COMMIT);

        if (SQL_SUCCESS != ret_value)
        {

                printf("\n failed line = %u: expect SQL_SUCCESS, but ret = %d", __LINE__, ret_value);
                return SQL_ERROR;
        }
        else
        {
                printf("sqlendtrans success .... \n");
        }

        while (1)
        {
        }
        // end_unit_test();
}

/*****************************************************************************
 *  *  函 数 名  : print_error
 *   *  功能描述  : 打印连接上的错误信息
 *    *  输出参数  : 无
 *     *  返 回 值  : int
 *      *  *****************************************************************************/

void print_error()
{
        // SQLCHAR Sqlstate[SQL_SQLSTATE_SIZE + 1];
        // SQLINTEGER NativeError;
        // SQLCHAR MessageText[MESSAGE_BUFFER_LEN];
        // SQLSMALLINT TextLength;
        // SQLRETURN ret = SQL_ERROR;
        // ret = SQLGetDiagRec(SQL_HANDLE_STMT, h_stmt, 1, Sqlstate, &NativeError, MessageText, MESSAGE_BUFFER_LEN, &TextLength);
        // if ( SQL_SUCCESS == ret)    {
        //         printf("\n STMT ERROR-%05d %s", NativeError, MessageText);
        //         return;    }
        // ret = SQLGetDiagRec(SQL_HANDLE_DBC, h_conn, 1, Sqlstate, &NativeError, MessageText, MESSAGE_BUFFER_LEN, &TextLength);
        // if ( SQL_SUCCESS == ret)    {
        //         printf("\n CONN ERROR-%05d %s", NativeError, MessageText);
        //         return;    }
        // ret = SQLGetDiagRec(SQL_HANDLE_ENV, h_env, 1, Sqlstate, &NativeError, MessageText, MESSAGE_BUFFER_LEN, &TextLength);
        // if ( SQL_SUCCESS == ret)    {
        //         printf("\n ENV ERROR-%05d %s", NativeError, MessageText);
        //         return;
        // }
        return;
}
void print_diag(char *msg, SQLSMALLINT htype, SQLHANDLE handle)
{
        char sqlstate[32];
        char message[1000];
        SQLINTEGER nativeerror;
        SQLSMALLINT textlen;
        SQLRETURN ret;
        if (msg)
                printf("%s\n", msg);
        ret = SQLGetDiagRec(htype, handle, 1, sqlstate, &nativeerror,
                            message, 256, &textlen);
        if (ret != SQL_ERROR)
                printf("%s=%s\n", (CHAR *)sqlstate, (CHAR *)message);
}

void print_result(HSTMT hstmt)
{
        // SQLRETURN rc;
        // SQLSMALLINT numcols;
        // rc = SQLNumResultCols(hstmt, &numcols);
        // if (!SQL_SUCCEEDED(rc)){
        //         print_diag("SQLNumResultCols failed", SQL_HANDLE_STMT, hstmt);
        //         return;
        // }
        // printf("Result set:\n");
        // while(1)
        // {
        //         rc = SQLFetch(hstmt);
        //         if (rc == SQL_NO_DATA)
        //                 break;
        //         if (rc == SQL_SUCCESS){
        //                 char buf[200];
        //                 int i;
        //                 SQLLEN ind;

        //                 for (i = 1; i <= numcols; i++)
        //                 {
        //                         rc = SQLGetData(hstmt,i, SQL_C_CHAR, buf, sizeof(buf), &ind);
        //                         if (!SQL_SUCCEEDED(rc)){
        //                                 print_diag("SQLGetData failed", SQL_HANDLE_STMT, hstmt);
        //                                 return;
        //                         }
        //                         if (ind == SQL_NULL_DATA)
        //                                 strcpy(buf, "NULL");
        //                         printf("%s%s", (i > 1) ? "\t" : "", buf);
        //                 }
        //                 printf("\n");
        //         }
        //         else{
        //                 print_diag("SQLFetch failed", SQL_HANDLE_STMT, hstmt);
        //                 exit(1);
        //         }
        // }
}
int commit_exec()
{
        // if ( SQL_SUCCESS != SQLExecute(h_stmt)){
        //         return SQL_ERROR;
        // }
        return SQL_SUCCESS;
}

int execute_cmd(SQLCHAR *sql)
{
        // if ( NULL == sql ){
        //         return SQL_ERROR;
        // }
        // if ( SQL_SUCCESS != SQLPrepare(h_stmt, sql, SQL_NTS)){
        //         print_diag(" SQLPrepare failed.", SQL_HANDLE_STMT, h_stmt);
        //         return SQL_ERROR;
        // }
        // if ( SQL_SUCCESS != SQLExecute(h_stmt)){
        //         print_diag(" SQLExecute failed.", SQL_HANDLE_STMT, h_stmt);
        //         return SQL_ERROR;
        // }
        return SQL_SUCCESS;
}
void end_unit_test()
{
        /* 释放语句句柄 */
        // if (NULL != h_stmt){
        //         SQLFreeHandle(SQL_HANDLE_STMT, h_stmt);
        // }
        // /* 释放连接句柄 */
        // if (NULL != h_conn){
        //         SQLDisconnect(h_conn);
        //         SQLFreeHandle(SQL_HANDLE_DBC, h_conn);
        // }
        // /* 释放环境句柄 */
        // if (NULL != h_env){
        //         SQLFreeHandle(SQL_HANDLE_ENV, h_env);
        // }
        return;
}
